﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UObject = UnityEngine.Object;

public class HotUpdate : MonoBehaviour {

    byte[] m_ReadPathFileListData;
    byte[] m_ServerFileListData;

    internal class DownFileInfo
    {
        public string url;
        public string fileName;
        public DownloadHandler fileData;
    }
    //下载文件数量
    int m_DownloadCount;

    /// <summary>
    /// 下载单个文件（获得文件信息）
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
	IEnumerator DownLoadFile(DownFileInfo info,Action<DownFileInfo> Complete)
    {
        UnityWebRequest webRequest = UnityWebRequest.Get(info.url);
        yield return webRequest.SendWebRequest();
        if(webRequest.isHttpError || webRequest.isNetworkError)
        {
            Debug.LogError("第1次,下载文件出错：" + info.url);
            //重试
            //for(int i = 0; i < 5; i ++)
            //{                            
            //    yield return webRequest.SendWebRequest();
            //    if (webRequest.isHttpError || webRequest.isNetworkError)
            //    {
            //        Debug.LogErrorFormat("第{0}次，下载文件出错：{1}", i + 2, info.url);
            //    }              
            //}
            yield break;
        }
        yield return new WaitForSeconds(0.2f);
        info.fileData = webRequest.downloadHandler;
        Complete?.Invoke(info);
        webRequest.Dispose();
    }

    /// <summary>
    /// 下载多个文件
    /// </summary>
    /// <param name="info"></param>
    /// <param name="Complete"></param>
    /// <returns></returns>
    IEnumerator DownLoadFile(List<DownFileInfo> infos, Action<DownFileInfo> Complete,Action DownLoadAllComplete)
    {
        foreach(DownFileInfo info in infos)
        {
            yield return DownLoadFile(info, Complete);
        }
        DownLoadAllComplete?.Invoke();
    }

    private List<DownFileInfo> GetFileList(string fileData,string path)
    {
        string content = fileData.Trim().Replace("\r", "");
        string[] files = content.Split('\n');
        List<DownFileInfo> downFileInfos = new List<DownFileInfo>(files.Length);
        for(int i = 0; i < files.Length;i++)
        {
            string[] info = files[i].Split('|');
            DownFileInfo fileInfo = new DownFileInfo();
            fileInfo.fileName = info[1];
            fileInfo.url = Path.Combine(path, info[1]);
            downFileInfos.Add(fileInfo);
        }
        return downFileInfos;
    }

    GameObject loadingObj;
    LoadingUI loadingUI;
    private void Start()
    {
        GameObject go = Resources.Load<GameObject>("LoadingUI");
        loadingObj = Instantiate(go);
        loadingObj.transform.SetParent(this.transform);
        loadingUI = loadingObj.GetComponent<LoadingUI>();

        if(IsFirstInstall())
        {
            ReleaseResources();
        }
        else
        {
            CheckUpdate();
        }
    }

    private bool IsFirstInstall()
    {
        //判断只读目录是否存在版本文件
        bool isExistsReadPath = FileUtil.IsExists(Path.Combine(PathUtil.ReadPath, AppConst.FileListName));

        //判断可读写目录是否存在版本文件
        bool isExistsReadWritePath = FileUtil.IsExists(Path.Combine(PathUtil.ReadWritePath, AppConst.FileListName));

        return isExistsReadPath && !isExistsReadWritePath;
    }

    //获得本地版本信息
    private void ReleaseResources()
    {
        m_DownloadCount = 0;
        string url = Path.Combine(PathUtil.ReadPath, AppConst.FileListName);
        DownFileInfo info = new DownFileInfo();
        info.url = url;
        StartCoroutine(DownLoadFile(info,OnDownLoadReadPathFileListComplete));
    }

    //解析版本信息然后释放文件(写到可读写目录中)
    private void OnDownLoadReadPathFileListComplete(DownFileInfo file)
    {
        m_ReadPathFileListData = file.fileData.data;
        List<DownFileInfo> fileInfos = GetFileList(file.fileData.text,PathUtil.ReadPath);
        StartCoroutine(DownLoadFile(fileInfos,OnReleaseFileComplete,OnReleaseAllFileComplete));
        loadingUI.InitProgress(fileInfos.Count, "正在释放资源，不消化流量...");
    }

    //释放文件
    private void OnReleaseFileComplete(DownFileInfo fileInfo)
    {
        Debug.Log("OnUpDateFileComplete:" + fileInfo.url);
        string writeFile = Path.Combine(PathUtil.ReadWritePath, fileInfo.fileName);
        FileUtil.WriteFile(writeFile, fileInfo.fileData.data);
        m_DownloadCount++;
        loadingUI.UpdateProgress(m_DownloadCount);
    }

    //写入版本信息，并检查更新
    private void OnReleaseAllFileComplete()
    {
        FileUtil.WriteFile(Path.Combine(PathUtil.ReadWritePath,AppConst.FileListName),m_ReadPathFileListData);
        CheckUpdate();
    }

    //获得服务器上的版本信息
    private void CheckUpdate()
    {
        string url = Path.Combine(AppConst.ResourcesUrl, AppConst.FileListName);
        DownFileInfo info = new DownFileInfo();
        info.url = url;
        StartCoroutine(DownLoadFile(info,OnDownLoadServerFileListComplete));
    }

    //检查更新
    private void OnDownLoadServerFileListComplete(DownFileInfo file)
    {
        m_DownloadCount = 0;
        m_ServerFileListData = file.fileData.data;
        List<DownFileInfo> fileInfos = GetFileList(file.fileData.text,AppConst.ResourcesUrl);
        List<DownFileInfo> downListFiles = new List<DownFileInfo>();
        m_DownloadCount = 0;
        for(int i =0; i< fileInfos.Count;i++)
        {
            string localFile = Path.Combine(PathUtil.ReadWritePath, fileInfos[i].fileName);

            //存疑，如果有已经存在的资源名需要更新呢？  
            //通过文件的MD5来进行校验
            if (!FileUtil.IsExists(localFile))
            {
                
                fileInfos[i].url = Path.Combine(AppConst.ResourcesUrl, fileInfos[i].fileName);
                downListFiles.Add(fileInfos[i]);
            }                         
        }

        if (downListFiles.Count > 0)
        {
            StartCoroutine(DownLoadFile(fileInfos, OnUpDateFileComplete, OnUpdateAllFileComplete));
            loadingUI.InitProgress(downListFiles.Count, "正在更新...");
        }          
        else
            EntenGame();
    }

    private void OnUpDateFileComplete(DownFileInfo file)
    {
        Debug.Log("OnUpDateFileComplete:"+file.url);
        string writeFile = Path.Combine(PathUtil.ReadWritePath, file.fileName);
        FileUtil.WriteFile(writeFile, file.fileData.data);
        m_DownloadCount++;
        loadingUI.UpdateProgress(m_DownloadCount);
    }

    private void OnUpdateAllFileComplete()
    {
        FileUtil.WriteFile(Path.Combine(PathUtil.ReadWritePath, AppConst.FileListName), m_ServerFileListData);
        EntenGame();
        loadingUI.InitProgress(0, "正在载入...");
    }

    private void EntenGame()
    {
        Manager.Event.Fire((int)GameEvent.GameInit);
        Destroy(loadingObj);
        //Manager.Resource.ParseVersionFile();
        //Manager.Resource.LoadUI("Login/LoginUI",OnComplete);
    }

    //private void OnComplete(UObject obj)
    //{
    //    GameObject go = Instantiate(obj) as GameObject;
    //    go.transform.SetParent(this.transform);
    //    go.SetActive(true);
    //    go.transform.localPosition = Vector3.zero;
    //}
}
